package hos.kotlin


/**
 * <p>Title: AnyExt </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2022/7/1 21:15
 * @version : 1.0
 */

fun Any?.isEmptyAny(): Boolean {
    if (this == null) {
        return true
    }
    if (this is CharSequence) {
        val targetCase = this.toString()
        return targetCase.isEmpty() || targetCase == "null" || targetCase == "Null" || targetCase == "NULL"
    }
    if (this is Number && this.toString() == "NaN") {
        return true
    }
    if (this.javaClass.isArray && java.lang.reflect.Array.getLength(this) == 0) {
        return true
    }
    if (this is CharSequence && this.toString().isEmpty()) {
        return true
    }
    if (this is Collection<*> && this.isEmpty()) {
        return true
    }
    if (this is Map<*, *> && this.isEmpty()) {
        return true
    }
    return false
}

fun Any?.isNotEmptyAny(): Boolean = !isEmptyAny()

fun Any?.equal(o2: Any?): Boolean {
    if (this == o2) {
        return true
    }
    if (this is CharSequence && o2 is CharSequence) {
        val a = this
        val b = o2
        var length: Int
        if (a.length.also { length = it } == b.length) {
            return if (a is String && b is String) {
                a == b
            } else {
                for (i in 0 until length) {
                    if (a[i] != b[i]) return false
                }
                true
            }
        }
    }
    return this != null && this == o2
}

fun Any?.notEqual(o2: Any?): Boolean = this.equal(o2)


//<editor-fold desc="T">
fun <T> T?.compare(b: T?, c: Comparator<in T>): Int = if (this == b) 0 else c.compare(this, b)

/**
 * Checks that the specified object reference is not `null`.
 */
fun <T> T?.requireNonNull(ifNullTip: String? = null): T {
    if (this == null) throw NullPointerException(ifNullTip)
    return this
}


fun <T> T?.getIfNull(value: T): T = if (this.isEmptyAny()) value else this!!

fun <T> T?.getIfNull(value: () -> T): T =
    if (this.isEmptyAny()) value.invoke() else this!!
fun Any?.toNull(): Any? = if (isEmptyAny()) null else this
//</editor-fold>

//<editor-fold desc="String">
fun Any?.toNullString(): String? {
    val target = this.toNull() ?: return null
    return target.toString()
}

fun Any?.empty(value: String = "", start: String = "", end: String = ""): String {
    val target = toNullString() ?: return start + value + end
    return start + target + end
}

fun Any?.empty(start: String = "", end: String = "", value: () -> String): String {
    val target = toNullString() ?: return start + value + end
    return start + target + end
}

fun Any?.divide(): String {
    return empty("-")
}

fun Any?.rate(value: String = ""): String {
    return empty(end = "%", value = value)
}

fun Any?.like(value: String = ""): String {
    val like = toNullString() ?: return "%$value%"
    return "%$like%"
}

fun Any?.like(value: () -> String): String {
    val like = toNullString() ?: return "%${value.invoke()}%"
    return "%$like%"
}

//</editor-fold>


//<editor-fold desc="Number">
fun Any?.isYesOrNo(yes: String = "是", no: String = "否"): String {
    return if (asBoolean()) yes else no
}

fun Any?.asInteger(value: Int = 0): Int {
    val target: Any = toNull() ?: return value
    if (target is Int) {
        return target
    }
    if (target is Number) {
        return target.toInt()
    }
    if (target is Boolean) {
        if (target) {
            return 1
        }
        return 0
    }
    if (target is String) {
        if (target.equal("true")) {
            return 1
        }
        if (target.equal("false")) {
            return 0
        }
        try {
            return target.toInt()
        } catch (ignored: NumberFormatException) {
        }
    }
    throw java.lang.RuntimeException("this is Number Or Boolean Or String")
}

fun Any?.toNullInteger(): Int? {
    val target: Any = toNull() ?: return null
    if (target is Int || target is Number || target is Boolean || target is String) {
        return target.asInteger()
    }
    throw java.lang.RuntimeException("this is Number Or Boolean Or String")
}

fun Any?.toNullIntegerString(): String? = toNullInteger().toNullString()

fun Any?.asIntegerString(value: Int = 0): String {
    val target: Int = toNullInteger() ?: return value.toString()
    return target.empty(value.toString())
}

fun Any?.asDouble(value: Double = 0.0): Double {
    val target: Any = toNull() ?: return value
    if (target is Double) {
        return target
    } else if (target is Number) {
        return target.toDouble()
    } else if (target is Boolean) {
        if (target) {
            return 1.0
        }
        return 0.0
    } else if (target is String) {
        if (target.equal("true")) {
            return 1.0
        }
        if (target.equal("false")) {
            return 0.0
        }
        try {
            return target.toDouble()
        } catch (ignored: java.lang.NumberFormatException) {
        }
    }
    throw java.lang.RuntimeException("this is Number Or Boolean Or String")
}

fun Any?.toNullDouble(): Double? {
    val target = toNull() ?: return null
    if (target is Double || target is Number || target is Boolean || target is String) {
        return target.asDouble()
    }
    throw java.lang.RuntimeException("this is Number Or Boolean Or String")
}

fun Any?.toNullDoubleString(): String? = toNullDouble().toNullString()

fun Any?.asDoubleString(value: Double = 0.0): String {
    val target: Double = toNullDouble() ?: return value.toString()
    return target.empty(value.toString())
}


fun Any?.asLong(value: Long = 0L): Long {
    val target: Any = toNull() ?: return value
    if (target is Long) {
        return target
    } else if (target is Number) {
        return target.toLong()
    } else if (target is Boolean) {
        if (target) {
            return 1
        }
        return 0
    } else if (target is String) {
        if (target.equal("true")) {
            return 1
        }
        if (target.equal("false")) {
            return 0
        }
        try {
            return target.toLong()
        } catch (ignored: java.lang.NumberFormatException) {
        }
    }
    throw java.lang.RuntimeException("this is Number Or Boolean Or String")
}

fun Any?.toNullLong(): Long? {
    val target: Any = toNull() ?: return null
    if (target is Long || target is Number || target is Boolean || target is String) {
        return target.asLong()
    }
    throw java.lang.RuntimeException("this is Number Or Boolean Or String")
}

fun Any?.toNullLongString(): String? = toNullLong().toNullString()
fun Any?.asLongString(value: Long = 0L): String {
    val target: Long = toNullLong() ?: return value.toString()
    return target.empty(value.toString())
}


fun Any?.asFloat(value: Float = 0f): Float {
    val target: Any = toNull() ?: return value
    if (target is Float) {
        return target
    } else if (target is Number) {
        return target.toFloat()
    } else if (target is Boolean) {
        if (target) {
            return 1f
        }
        return 0f
    } else if (target is String) {
        if (target.equal("true")) {
            return 1f
        }
        if (target.equal("false")) {
            return 0f
        }
        try {
            return target.toFloat()
        } catch (ignored: java.lang.NumberFormatException) {
        }
    }
    throw java.lang.RuntimeException("this is Number Or Boolean Or String")
}

fun Any?.toNullFloat(): Float? {
    val target = toNull() ?: return null
    if (target is Float || target is Number || target is Boolean || target is String) {
        return target.asFloat()
    }
    throw java.lang.RuntimeException("this is Number Or Boolean Or String")
}

fun Any?.toNullFloatString(): String? = toNullFloat().toNullString()

fun Any?.asFloatString(value: Float = 0f): String {
    val target: Float = toNullFloat() ?: return value.toString()
    return target.empty(value.toString())
}

fun Any?.asBoolean(value: Boolean = false): Boolean {
    val target: Any = toNull() ?: return value
    if (target is Boolean) {
        return target
    } else if (target is String) {
        if ("true".equals(target, ignoreCase = true)) {
            return true
        } else if ("false".equals(target, ignoreCase = true)) {
            return false
        } else if ("是".equals(target, ignoreCase = true)) {
            return true
        } else if ("否".equals(target, ignoreCase = true)) {
            return false
        } else if ("1".equals(target, ignoreCase = true)) {
            return true
        } else if ("0".equals(target, ignoreCase = true)) {
            return false
        }
        return target.toBoolean()
    } else if (target is Int) {
        if (target == 0) {
            return false
        } else if (target == 1) {
            return true
        }
    } else if (target is Float) {
        if (target == 0f) {
            return false
        } else if (target == 1f) {
            return true
        }
    } else if (target is Long) {
        if (target == 0L) {
            return false
        } else if (target == 1L) {
            return true
        }
    } else if (target is Double) {
        if (target == 0.0) {
            return false
        } else if (target == 1.0) {
            return true
        }
    }
    throw java.lang.RuntimeException("this is Number Or Boolean Or String")
}

fun Any?.toNullBoolean(): Boolean? {
    val target: Any = toNull() ?: return null
    if (target is Boolean || target is Number || target is String) {
        return target.asBoolean()
    }
    throw java.lang.RuntimeException("this is Number Or Boolean Or String")
}

fun Any?.toNullBooleanString(): String? = toNullBoolean().toNullString()

fun Any?.asBooleanString(value: Boolean = false): String {
    val target: Boolean = toNullBoolean() ?: return value.toString()
    return target.empty(value.toString())
}
//</editor-fold>

